
var autosave = false; // autosave after every edit of task details? make it a userpref?

var C_MAPS_QUERY_URL = 'http://maps.google.com/maps?f=q&q=';

// Redraw task details DOM element with refreshed task data
function taskDetailsViewRefresh(detviewDOM, task) {
	var tid = detviewDOM.tid;
	var $d = $(detviewDOM);
	var id = $d[0].id;
	
	$d.find('.dtitle .field').text(task.title);
	if (task.dueDate)
		$d.find('.ddue .field').text(task.dueDate.toString("ddd dd MMM yyyy HH:mm"));
	
	$d.find('.ddue a').DatePicker({
			format:'m/d/Y',
			date: new Date(),
			current: new Date(),
			starts: 1,
			onBeforeShow: function() {
				var ds = validDate($('#' + id).find('.ddue .field').text());
				if (!ds) ds = new Date();
				$(this).DatePickerSetDate(ds, true);
			},
			onChange: function(formated) {
				$('#' + id).find('.ddue .field').text(formated);
			}
	}); // datepicker
	
	if (task.addedDate)
		$d.find('.dcreated .data').text(task.addedDate.toString("M/d/yyyy \a\\t HH:mm") + ' by ' + task.creator);
	if (task.lastModified)
		$d.find('.dmodified .data').text(task.lastModified.toString("M/d/yyyy \a\\t HH:mm") + ' by ' + task.lastModifier);
	if (task.isCompleted()) {
		$d.find('.dcompleted .data').text(task.completedDate.toString("M/d/yyyy \a\\t HH:mm") + ' by ' + task.completer);
		$d.find('.dcompleted').removeClass('hidden');
	}
	if (task.freq)
		$d.find('.dfreq .field').text(task.freq);
	if (task.dur)
		$d.find('.ddur .field').text(task.dur);
	if (task.location) {
		$d.find('.dlocation .field').text(task.location);
		var anc = $d.find('.dlocation a')[0];
		anc.href = C_MAPS_QUERY_URL + task.location;
		anc.target = '_blank';
	}
	if (task.link) {
		$d.find('.dlink .field').text(task.link);
		var anc = $d.find('.dlink a')[0];
		anc.href = task.link;
		anc.target = '_blank';
	}
	if (task.owner.length > 0) {
		$d.find('.downer .field').text(task.owner);
		$d.find('.downer').removeClass('hidden');
	}
	if (task.progress)
		$d.find('.dprogress .field').text(task.progress);
	if (task.status)
		$d.find('.dstatus .field').text(task.status);

	// tags:
	if(task.tags && task.tags.length > 0) {
		var tagStr = task.tags[0];
		if(task.tags.length > 1)
			tagStr = accumulate(tagStr, task.tags.slice(1), function(acc, tag) {
				return acc + ", " + tag;
			});
		$d.find('.dtags span.field').text(tagStr);
	}
}

function taskDetailsViewSave(detviewDOM) {
	var tid = detviewDOM.tid;
	var $dv = $(detviewDOM);
	var tc = cloneTask($dv[0].task);
	var v = true;
	
	var $fields = $dv.children('span');
	for (var i = 0; i < $fields.length; i++) { // check all fields
		var $f = $($fields[i]).find('.field');
		if ($f.length <= 0) continue;
		var ftype = $fields[i].className.split(' ')[0];
		var val = jQuery.trim($f.text());
		v = v && taskDetailsViewValidateValue(val, ftype);
		if (!v) break; // invalid edits
		var l = val.length, e = (l == 0);
		
		// save to task
		if (ftype == 'ddue') tc.dueDate = e ? null : validDate(val);
		else if (ftype == 'dfreq') tc.freq = e ? '' : validFrequency(val);
		else if (ftype == 'ddur') tc.dur = e ? '' : validDuration(val);
		else if (ftype == 'dlink') tc.link = e ? '' : validLink(val);
		else if (ftype == 'dtitle') tc.title = val;
		else if (ftype == 'dlocation') tc.location = val;
		else if (ftype == 'downer') tc.owner = val;
		else if (ftype == 'dprogress') tc.progress = e ? '' : validProgress(val);
		else if (ftype == 'dstatus') tc.status = val;
		else if (ftype == 'dtags') {
			tc.tags = [];
			val = val.split(',');
			for (var j = 0; j<val.length; j++) {
				var tagi = jQuery.trim(val[j]);
				if (tagi.length > 0) tc.tags.push(tagi);
			}
		}
	}
	
	if (v) {
		updateTask(tc);
		return true;
	} else {
		return false;
	}
}

// Validate text value by type. Returns false if invalid.
function taskDetailsViewValidateValue(val, ftype) {
	var isvalid = true, v = true;
	var aftypes = ftype.split(' ');
	for (var i = 0; i < aftypes.length; i++) {
		var ftype = aftypes[i];
		if (ftype == 'ddue') v = validDate(val);
		else if (ftype == 'dfreq') v = validFrequency(val);
		else if (ftype == 'ddur') v = validDuration(val);
		else if (ftype == 'dprogress') v = validProgress(val);
		else if (ftype == 'dlink') v = validLink(val);
		
		if (val.length <= 0) v = true; // accept empty fields
		
		if (ftype == 'dtitle') v = val.length > 0;
		isvalid = isvalid && (v != false);
	}
	return isvalid;
}

// Validate editor user input field, updates details view.
function taskDetailsViewValidateField(field) {
	var $f = $(field);
	var $pspan = $f.closest('span:not([class=field])');
	if ($pspan.length <= 0) return;
	var ftype = $pspan[0].className;
	var aftypes = ftype.split(' ');
	var val = jQuery.trim($f.val());
	var isvalid = taskDetailsViewValidateValue(val, ftype);
	
	var detviewDOM = $f.closest('div.tsk_details')[0];
	
	if (isvalid) {
		$f.closest('span').css('color','#093').text($f.val());
		
		// update links, etc
		var $a = $pspan.find('a');
		if ($a.length > 0) {
			$a[0].target = '_blank';
			if (aftypes[0] == 'dlink') 
				$a[0].href = val;
			if (aftypes[0] == 'dlocation') 
				$a[0].href = C_MAPS_QUERY_URL + val;
		}
		
		if (autosave) {
			taskDetailsViewSave(detviewDOM);
		}
	} else {
		$f.closest('span').css('color','#930').text($f.val());
		if (autosave) {
			taskDetailsViewRefresh(detviewDOM, detviewDOM.task);
		}
	}
}

// Text validation routines. Return false if invalid, or object if valid.
function validDate(date) {
	date = getNextWeekday(date.toLowerCase());
	var d = Date.parse(date); // date.js
	if (d) return d;
	return false;
}

function validFrequency(freq) {
	var ix = jQuery.inArray(freq, ac_freq);
	if (ix != -1)
		return freq;
	var reg = new RegExp('^(after|every)\\s+\\d+\\s+(day|week|month|year)s?\\s*$','g');
	var m = freq.match(reg);
	if (m) return jQuery.trim(m[0]);
	return false;
}

function validDuration(dur) {
	var reg = new RegExp('^\\d+\\s*(m|min|h|hr|hour)s?\\s*$','g');
	var m = dur.match(reg);
	if (m) return jQuery.trim(m[0]);
	return false;
}

function validPriority(p) {
	var k = parseInt(p);
	return k <= 4 && k >= 1 ? k : false;
}

function validProgress(p) {
	var k = parseInt(p);
	return k <= 100 && k >= 0 ? k : false;
}

function validLink(url) {
	var reg = new RegExp('^(f|ht)tps?:\\/\\/\\S+\\s?$','g');
	var m = url.match(reg);
	if (m) return jQuery.trim(m[0]);
	return false;
}

function getNextWeekday(str) {
	for (var i = 0; i < ac_days.length; i++)
		if (str == ac_days[i].toLowerCase()) return 'next ' + str;
	return str;
}


/*
 * Close the open task details for task #tid
 * if tid=null, close all
 */
function closeOpenTaskDetailsView(tid) {
	
	var openViews;
	
	if(tid == null)
		openViews = $('.tsk_list .tsk_details'); // don't choose template
	else
		openViews = $('#tsk_details_' + tid);
	
	// if any, just one
	if(openViews.length > 0) {
		openViews[0].closeView();
	}
}


/*
 * Init the task details view/editor onclick. 
 * Note that this relies on current GUI properties.
 */ 
function initDetailsView() {
	// on row click show the details view
	$('.tsk_row .cell_edit_icon').click(function(event) {
		// ignore checkbox clicks, ctrl
		//if (event.target.type == 'checkbox' ||
		//    ($.specialKeys('ctrl'))) return;
		is_cbox_hit = true;
		
		
		var tskRow = $(this).closest(".tsk_row")[0];
		
		// hide open view (uncomment to show only one at a time)
		//$('.tsk_details.open').slideUp(300, function() {$(tskRow).remove();});
		
		var tid = tskRow.id;
		var t = tskRow.task;
		
		// hide if already open
		
		var owndv = $('#tsk_details_' + tid);
		var isAlreadyOpen = (owndv.length > 0);
		
		if (isAlreadyOpen)
			closeOpenTaskDetailsView(tid);
		else {
			
			closeOpenTaskDetailsView();
			
			// open new view
			var newDet = $('#tsk_details_template').clone(true)[0];
			newDet.taskid = tid;
			newDet.task = t;
			newDet.id = 'tsk_details_' + tid;
			
			newDet.closeView = function() {
				$('#'+newDet.id).slideUp(300, function() {
					$('#'+newDet.id).remove();
					adjustGadgetHeight();
				});
			}

			taskDetailsViewRefresh(newDet, t);

			// set events:
			// onclick edit field
			$(newDet).children('span').click(function(e) {
				var $field = $(this).find('.field');
				if ($field.length <= 0 || $field.find('input').length > 0 || e.target.href)
					return;
				var txt = $field.text();
				var wdt = parseInt($field.get(0).offsetWidth) + 20;
				if (wdt < 100) wdt = 100; wdt += 'px';
				//wdt = "60%";
				$field.html(
					'<form action="#" onsubmit="$(this).find(\'input\').blur(); return false;" style="display: inline"><input class="inputtext" type="text" style="width: ' +
					wdt + '" value="' +txt+ '" /></form>'
				);
				var $edit = $field.find(':text');

				var $pspan = $field.closest('span:not([class=field])');
				if ($pspan.length <= 0) ftype = 'empty';
				var ftype = $pspan[0].className.split(' ')[0];
				
				if (ftype == 'downer') {
					var partis = wave.getParticipants();
					$edit.autocomplete(partis, {
						max: 9,
						width: 'auto',
						minChars: 1,
						matchContains: true,
						highlightItem: false,
						formatItem: function(row,i,n,g,y) {
							return "<img src='" + row.getThumbnailUrl() + "' class='cell_icon' /> " + row.getDisplayName().replace(new RegExp("(" + y + ")", "gi"), "<strong>$1</strong>") + " &lt;" + row.getId() + "&gt;";
						},
						formatResult: function(row) {return row.getId();}
					});
				}
				else {
					$edit.autocomplete(dvfield_2_acarr[ftype], {
						max: 9,
						width: 'auto',
						multiple: ftype == 'dtags' ? true : false,
						multipleSeparator: ", "
					});
				}

				$edit.focus();
				$edit.blur(function(e) {
					taskDetailsViewValidateField(this);
				});
			});
			
			$(newDet).children('span').hover( // hover
				function(e) { $(this).addClass('tsk_row_hover');},
				function(e) { $(this).removeClass('tsk_row_hover');}
			);
			
			$(newDet).find('a[name=save]').click(function(e) { // save
				var rv = taskDetailsViewSave($('#'+newDet.id)[0]);
				if (rv) $('#'+newDet.id)[0].closeView();
			});
			
			$(newDet).find('a[name=close]').click(function(e) { //close
				$('#'+newDet.id)[0].closeView();
			});
			
			$(newDet).find('a[name=gcalquickadd]').click(function(e) { //gcalquickadd
				gcalQuickAdd($('#'+newDet.id)[0].task);
			});
			
			
			// for the task to wave discussion feature:
			if (t.isLinkedToWave()) {
				$(newDet).find('a[name=discuss]').text("Discuss (join)");
				$(newDet).find('a[name=discuss]')[0].href = t.getLinkedWaveHref();
				$(newDet).find('a[name=discuss]')[0].target = '_top';
			}
			
			$(newDet).find('a[name=discuss]').click(function(e) { //discuss
				var robot = wave.getParticipantById(ROBOTID);
				if (!robot) {
					alert('For this feature you currently need the robot to join your wave. To utilize it, invite '+ROBOTID+' to your wave. See http://code.google.com/p/todoit-wave/ for more.');
				} else {
					($('#'+newDet.id)[0].task).createLinkedWave();
				}
			});
			
			// display
			$(tskRow).after(newDet);
			$(newDet).addClass('open');
			$(newDet).slideDown(300, function() {
				$(this).removeClass('hidden').attr("style", "");
				adjustGadgetHeight();
			});
		}
		
	});
	
}
